PATH![]() |
![]() ![]() |
The Mac OS 8.5 Window Manager provides system support for your application to display window path pop-up menus--like those used in Finder windows. When the user presses the Command key and clicks on the window's title, the window displays a pop-up menu containing a standard file system path, informing the user of the location of the document displayed in the window and allowing the user to open windows for folders along the path.
Because the window title includes both the proxy icon region and part of the drag region of the window, your application must be prepared to respond to a click in either region by displaying a window path pop-up menu. Therefore, when the FindWindow function returns either the inDrag or the inProxyIcon result code--you should pass the event to the function IsWindowPathSelectClick to determine whether the mouse-down event should activate the window path pop-up menu. If IsWindowPathSelectClick returns a value of true , your application should then call the function WindowPathSelect to display the menu. Listing 2-5 shows how your application might handle a user request to display the window path pop-up menu.
Listing 2-5 Determining whether to display the window path pop-up menu
case mouseDown:
{
short part = FindWindow(pEvent->where, &pWindow);
switch ( part )
{
case inProxyIcon:
// We've seen a hit in the window proxy area, so drag the proxy icon
// Note that we don't check that the window is an app window, but you should
{
OSStatus status = TrackWindowProxyDrag( pWindow, pEvent->where );
if( status == errUserWantsToDragWindow )
handled = false;
else if( status == noErr )
handled = true;
}
// fall through
case inDrag:
if( !handled )
// Check that we should show the window file path pop-up menu
{
// Note that we don't check that the window
// is an app window, but you should
{
if( IsWindowPathSelectClick( pWindow, pEvent ) )
{
SInt32 itemSelected;
if(WindowPathSelect( pWindow, NULL, &itemSelected ) == noErr )
{
// If the menu item selected is not the title of the window
// itself, switch to the Finder, since the window chosen
// probably isn't visible
if( LoWord(itemSelected) > 1 )
{
MyBringFinderToFront();
}
}
handled = true;
}
}
if( !handled )
{
// Call DragWindow and drag the window
...
}
}
break;
}
break;
}
Note that in Listing 2-5 , the user may have selected a menu item for a folder representing a Finder window from the window path pop-up menu. Your application must ensure that the resulting window is visible to the user by making the Finder the frontmost process, as is shown in Listing 2-6 .
Listing 2-6 Bringing the Finder to the front
static void MyBringFinderToFront(void)
{
const OSType kFinderSignature = 'MACS';
const OSType kFinderType = 'FNDR';
ProcessSerialNumber finderProcess;
// If we find the Finder...
if( MyFindProcess( kFinderSignature, kFinderType, &finderProcess ) == noErr)
{
// Tell the Process Manager to bring the Finder to the front
(void) SetFrontProcess( &finderProcess );
}
else
{
// If the Finder can't be brought up, alert the user
...
}
}
As shown in Listing 2-6 , making the Finder the frontmost process requires that your application call the Process Manager function SetFrontProcess with the Finder's process serial number to bring the Finder to the front. Listing 2-7 provides an example of how your application may obtain the Finder's process serial number.
Listing 2-7 Finding the process serial number of a process
// Find the PSN of a process, in this case, the Finder,
// given a type and creator pair corresponding to the type
// and creator of the file from which the process was launched.
static OSStatus MyFindProcess( OSType creator, OSType type, ProcessSerialNumber *outProcess )
{
ProcessInfoRec theProc;
OSStatus outStatus = 0L;
ProcessSerialNumber psn;
// Start from kNoProcess
psn.highLongOfPSN = 0;
psn.lowLongOfPSN = kNoProcess;
// Initialize ProcessInfoRec fields, or we'll have memory hits in random locations
theProc.processInfoLength = sizeof( ProcessInfoRec );
theProc.processName = nil;
theProc.processAppSpec = nil;
theProc.processLocation = nil;
while(true)
{
// Keep looking for the process until we find it
outStatus = GetNextProcess(&psn);
if( outStatus != noErr )
break;
// Is the current process the one we're looking for?
outStatus = GetProcessInformation(&psn, &theProc);
if( outStatus != noErr )
break;
if( (theProc.processType == type ) && (theProc.processSignature == creator) )
break;
}
*outProcess = psn;
return outStatus;
}